﻿using System;
using System.IO;
using System.Diagnostics;
using System.Web;

namespace CommonTools
{
    public class HTMLProcessor : Stream
    {
        private const string TIDY_EXE = "tidy.exe";
        private const string TIDY_CFG = "tidy.cfg";
        private const int BUFFER_SIZE = 1024 * 4;    // 4096

        private Stream internalStream;
        private long position;
        private MemoryStream memStream;
        
        public HTMLProcessor (Stream stream)
        {
            internalStream = stream;
            memStream = new MemoryStream ();
        }
            
        public override bool  CanRead
        {
	        get { return true; }
        }

        public override bool  CanSeek
        {
	        get { return true ; }
        }

        public override bool  CanWrite
        {
	        get {  return true ; }
        }

        public override void  Flush()
        {
 	        internalStream.Flush();
        }

        public override long  Length
        {
	        get { return internalStream.Length; }
        }

        public override long  Position
        {
	        get { return position;  }
	        set { position = value; }
        }

        public override int  Read(byte[] buffer, int offset, int count)
        {
 	        return internalStream.Read(buffer, offset, count);
        }

        public override long  Seek(long offset, SeekOrigin origin)
        {
 	        return internalStream.Seek(offset, origin);
        }

        public override void  SetLength(long value)
        {
 	        internalStream.SetLength (value) ;
        }

        public override void  Write(byte[] buffer, int offset, int count)
        {
 	        memStream.Write(buffer, offset, count);
        }

        public override void  Close()
        {
            try
            {
                String path = HttpContext.Current.Request.PhysicalApplicationPath;

                // Info about the process to be created
                ProcessStartInfo psi = new ProcessStartInfo ();
                psi.FileName = path + TIDY_EXE;
                psi.Arguments="-config " + path + TIDY_CFG;  
                psi.WorkingDirectory=path;
                psi.CreateNoWindow = true;
                psi.RedirectStandardInput = true;
                psi.RedirectStandardOutput = true;
                psi.RedirectStandardError = false;

                // Create the process for tidy.exe
                Process process = new Process ();
                process.StartInfo = psi;

                // Run Forest!!
                process.Start();

                // Now, we write into the standar input. Is like press keys 
                memStream.WriteTo(process.StandardInput.BaseStream); 
                process.StandardInput.Close();

                // we read input data from stdout and write him over internal straem.
                byte []buff = new byte[BUFFER_SIZE];
                int count = 0;

                do{
                    count = process.StandardOutput.BaseStream.Read(buff, 0, BUFFER_SIZE);
                    internalStream.Write(buff, 0, count);
                }while(count!=0);

                process.StandardOutput.Close();
            }
            catch(Exception ex)
            {
                memStream.WriteTo(internalStream);
            }
            finally 
            {
                internalStream.Close(); 
            }
        }
    }
}
